package com.diandi.log;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
//import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * log信息记录
 * Created by 袁恩光 on 2018/1/9.
 */
@Component
@Aspect
@Order(2)
public class LogAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    private LogProperties logProperties;

    /**
     * 日志记录
     */
    @Around("(execution( * com.diandi..*.*(..)) || execution( * com.ddshenbian..*.*(..)))  && !execution( * com.diandi.log.*.*(..))")
    public Object logAop(ProceedingJoinPoint point) throws Throwable {
        //传播方式判断 是否是step的log
        boolean isMain = false;
        long startTime = 0L;
        long totalTime = 0L;
        String methodName = ((MethodSignature) point.getSignature()).getMethod().getName();
        String className = point.getTarget().getClass().getSimpleName();
        if (null == LogTemp.LOG_TITLE_MESSAGE.get()) {
            LogTemp.LOG_TITLE_MESSAGE.set(new LinkedHashMap());
        }
        LogTemp.LOG_TITLE_MESSAGE.get().put("application", logProperties.getApplicationName());
        LogTemp.LOG_TITLE_MESSAGE.get().put("methodName", className + "." + methodName);
        //判断是在执行step还是主log
        if (LogTemp.LOG_MAIN_NAME.get() == null) {
            isMain = true;
            //获取 TradeNo 类名 方法名 并放入线程变量
            //log 头部信息拼接
            StringBuilder sb = new StringBuilder();
            sb.append(tradeNo());
            sb.append(className);
            sb.append(" ");
            sb.append(methodName);
            sb.append(" ");
            //保存到当前线程变量
            LogTemp.LOG_MAIN_NAME.set(sb.toString());
            //日志记录开始
            logger.info(LogTemp.LOG_MAIN_NAME.get() + "log_Start_log--");
            startTime = System.currentTimeMillis();
            LogTemp.LOG_STEP.set(0);
            LogTemp.LOG_STEP_TIME.set(startTime);
        } else {
            //step 执行的方法名
            String name = LogTemp.LOG_MAIN_NAME.get() + methodName + " ";
            LogTemp.LOG_MAIN_NAME.set(name);
        }
        //执行方法
        Object object = null;
        try {
            object = point.proceed();
        } catch (Throwable e) {
            if (isMain) {
                logger.info(LogTemp.LOG_MAIN_NAME.get() + "log_End_log methodException " + e.toString() + "--");
                Map<String, Object> map = new HashMap<>();
                map.putAll(LogTemp.LOG_TITLE_MESSAGE.get());
                map.put("error_msg", LogTemp.LOG_MAIN_NAME.get() + " log_End_log methodException " + e.toString() + "--");
//                MongoTemplate mongoTemplate = logProperties.getMongoTemplate();
//                if (null != mongoTemplate) {
//                    mongoTemplate.insert(map, logProperties.getLogErrorCollection());
//                }
                LogTemp.clean();
            }
            throw e;
        }
        if (!isMain) {
            //step log
            long stepTime = System.currentTimeMillis();
            //记录step日志
            int step = LogTemp.LOG_STEP.get() + 1;
            LogTemp.LOG_STEP.set(step);
            long diffTime = stepTime - LogTemp.LOG_STEP_TIME.get();
            LogTemp.LOG_STEP_TIME.set(stepTime);
            logger.info(LogTemp.LOG_MAIN_NAME.get() + "step" + step + " use times:" + diffTime + "--");
            //移除 step 所用的方法名
            String name = LogTemp.LOG_MAIN_NAME.get().replaceFirst(methodName, "");
            LogTemp.LOG_MAIN_NAME.set(name.trim() + " ");
        } else {
            //主log log结束
            totalTime = System.currentTimeMillis() - startTime;
            logger.info(LogTemp.LOG_MAIN_NAME.get() + "log_End_log TotalTimes:" + totalTime + "--");
            //清除所有log 线程变量
            LogTemp.clean();
        }
        return object;
    }


    private String tradeNo() {
        StringBuilder sb = new StringBuilder();
        sb.append("--【");
        sb.append("LOG_MONITOR-");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sb.append(sdf.format(new Date()));
        sb.append("-");
        sb.append(UUID.randomUUID().toString().replace("-", ""));
        sb.append("】");
        if (!LogTemp.LOG_TITLE_MESSAGE.get().containsKey("logTitle")) {
            LogTemp.LOG_TITLE_MESSAGE.get().put("logTitle", sb.toString().replace("--", "").trim());
        }
        return sb.toString();
    }


}
